/** 
 * @Description: 文件描述
 * @Author: 程前
 * @Date: 2025-02-11 09:14:53
 * @LastEditors: 程前
 * @LastEditTime: 2025-03-11 09:59:13
 */

import {
    Viewer,
    Entity,
    JulianDate,
    SampledPositionProperty,
    ClockRange,
    ClockStep,
    TimeIntervalCollection,
    TimeInterval,
    VelocityOrientationProperty,
    HermitePolynomialApproximation,
    LagrangePolynomialApproximation,
    Math as CesiumMath,
    Color,
    HeightReference,
    CallbackProperty,
    sampleTerrainMostDetailed,
    HeadingPitchRange,
    Cartographic,
    EllipsoidGeodesic,
    Cartesian3,
    createWorldTerrainAsync,
    ModelGraphics,
    PathGraphics,
    PolylineGraphics,
    LabelGraphics,
    CylinderGraphics,
    Quaternion,
    SampledProperty,
    Transforms,
    HeadingPitchRoll,
} from "cesium"
import { CylinderBeam } from "../../test/index"

/**
 * 定义时间戳位置数据接口
 */
interface TimePositionData {
    time: number;       // 时间戳（秒）
    latitude: number;   // 纬度
    longitude: number;  // 经度
    altitude: number;   // 高度
    heading?: number;   // 航向角
    pitch?: number;     // 俯仰角
    roll?: number;      // 翻滚角
}


interface RoamingOptions {
    time?: number;
    multiplier?: number;
    Lines?: Cartesian3[];
    model?: ModelGraphics.ConstructorOptions;
    path?: PathGraphics.ConstructorOptions;
    polyline?: PolylineGraphics.ConstructorOptions;
    label?: LabelGraphics.ConstructorOptions;
    cylinder?: CylinderGraphics.ConstructorOptions;
    ifAffixedTo?: boolean;
    ifClockLoop?: boolean;
    interpolation?: boolean;
    showLabel?: boolean;
    ifTileset?: boolean;
    radar?: boolean
    changeView?: boolean
}

interface RoamingData {
    shouldAnimate?: boolean;
    totalLength?: string;
    totalTime?: string;
    delTime?: string;
    roamingLength?: string;
    longitude?: string;
    latitude?: string;
    roamingElevation?: string;
    terrainHeight?: string;
    liftoffHeight?: string;
    progress?: string;
}

/**
   * @class DEUGlobe.Scene.Roaming
   * @category  场景
   * @classdesc 漫游
   * @param {Object} viewer -  viewer。
   * @param {Object} options -  参数。
   * @param {Boolean} options.time  -  漫游时间 。
   * @param {Boolean} options.multiplier  -  飞行速度 默认1。
   */
export default class Roaming {
    private viewer: Viewer;
    private pause: boolean;
    private Lines: Cartesian3[];
    private entity: Entity | undefined;
    private start: JulianDate | undefined;
    private stop: JulianDate | undefined;
    private time: number;
    private multiplier: number;
    private data: RoamingData;
    private ifClockLoop: boolean;
    private options: RoamingOptions;
    private ifAffixedTo: boolean;
    private interpolation: boolean;
    private showLabel: boolean;
    private ifTileset: boolean;
    private modelData: any;
    private polyline: Entity | undefined;
    private cylinder: Entity | undefined;
    private radar: Entity | undefined;
    private currentPosition: Cartesian3

    constructor(viewer: Viewer, options: RoamingOptions) {
        this.viewer = viewer;
        this.pause = true;
        this.options = options || {};
        this.Lines = [];
        this.entity = undefined;
        this.start = undefined;
        this.stop = undefined;
        this.time = !options.time ? 360 : options.time;
        this.multiplier = !options.multiplier ? 1 : options.multiplier;
        this.data = {};
        this.ifClockLoop = false;
        this.ifAffixedTo = false;
        this.interpolation = false;
        this.showLabel = false;
        this.ifTileset = false;
        this.modelData = {};
        this.polyline = undefined;
        this.cylinder = undefined;
    }
    /**
   *
   *
   * @param {*} Lines 点集合
   * @param {*} time 漫游时间
   * @param {*} start 开始时间节点
   * @returns
   * @memberof Roaming
   */
    private ComputeRoamingLineProperty(Lines: Cartesian3[], time: number): SampledPositionProperty {
        let property = new SampledPositionProperty();
        let lineLength = Lines.length;
        let tempTime = time;
        let start = JulianDate.now();
        this.start = start;
        let stop = JulianDate.addSeconds(start, time, new JulianDate());
        this.stop = stop;
        this.viewer.clock.startTime = start.clone();
        this.viewer.clock.stopTime = stop.clone();
        this.viewer.clock.currentTime = start.clone();
        if (this.ifClockLoop) {
            this.viewer.clock.clockRange = ClockRange.LOOP_STOP;
        } else {
            this.viewer.clock.clockRange = ClockRange.CLAMPED;
            this.viewer.clock.clockStep = ClockStep.SYSTEM_CLOCK;
        }
        this.viewer.clock.shouldAnimate = true;
        this.viewer.clock.multiplier = this.multiplier;
        for (let i = 0; i < lineLength; i++) {
            let time = JulianDate.addSeconds(start, i / lineLength * tempTime, new JulianDate());
            if (i == lineLength - 1) {
                time = stop;
            }
            let position = Lines[i];
            if (this.ifTileset) {
                position = this.viewer.scene.clampToHeight(position) || position;
            }
            property.addSample(time, position);
        };
        return property;
    }

    /**
    * @des 相机漫游
    * @param {Array} Lines -  点集合 (必填)。
   */
    private cameraRoaming(Lines) {
        this.Lines = Lines;
        let property = this.ComputeRoamingLineProperty(this.Lines, this.time);
        this.initRoaming(property, this.start, this.stop);
    }

    /**
     * @param {*} position computeRoamingLineProperty计算的属性
     * @param {*} start 开始时间节点
     * @param {*} stop 结束时间节点
     * @memberof Roaming
    */
    private initRoaming(position: SampledPositionProperty, start: JulianDate, stop: JulianDate) {
        this.entity = this.viewer.entities.add({
            availability: new TimeIntervalCollection([
                new TimeInterval({
                    start: start,
                    stop: stop
                })
            ]),
            position: position,
            orientation: new VelocityOrientationProperty(position)
        });

        if (this.entity.position instanceof SampledPositionProperty) {
            (this.entity.position as SampledPositionProperty).setInterpolationOptions({
                interpolationDegree: 100,
                interpolationAlgorithm: HermitePolynomialApproximation
            });
        }

        this.viewer.trackedEntity = this.entity;
        let camera = this.viewer.camera;
        const Exection = () => {
            if (this.entity) {
                let center = this.entity.position.getValue(this.viewer.clock.currentTime);
                if (center) {
                    camera.lookAt(center, {
                        heading: CesiumMath.toRadians(117.7),
                        pitch: CesiumMath.toRadians(0),
                        range: 100
                    });
                }
                if (this.viewer.clock.shouldAnimate) {
                    center && this.realTimeData(center)
                }
            } else {
                this.viewer.scene.preUpdate.removeEventListener(Exection);
            }
        }
        this.viewer.scene.preUpdate.addEventListener(Exection);
    }

    /**
     * @class DEUGlobe.Scene.Roaming.modelRoaming                                        
     * @classdesc 模型漫游
     * @param {Object} options -  参数。
     * @param {Cartesian3[]}  options.Lines  -  点集合 (必填)。
     * @param {Object} options.model - 模型  ModelGraphics.ConstructorOptions。
     * @param {Boolean} options.ifAffixedTo  - 是否贴地漫游 (默认 false)
     * @param {Boolean} options.ifClockLoop  - 是否循环漫游 (默认 false)
     * @param {Boolean} options.interpolation  - 是否弧形差值 (默认 false)
     * @param {Boolean} options.model.minimumPixelSize - 模型最小刻度 (默认 64)
     * @param {Object} options.path - 漫游轨迹 PathGraphics.ConstructorOptions。
     * @param {Boolean} options.path.show - 漫游轨迹可见性 (默认 false)
     * @param {Object} options.polyline - 绘制折线 PolylineGraphics.ConstructorOptions.
     * @param {Boolean} options.polyline.show  - 绘制折线可见性 (默认 false)
     * @param {Object} options.label  - 标注  LabelGraphics.ConstructorOptions
     * @param {Boolean} options.label.show  -标注可见性 (默认 false)
     * @param {Object} options.cylinder - 绘制圆柱体 CylinderGraphics.ConstructorOptions
     * @param {Boolean} options.cylinder.show  - 绘制折线可见性 (默认 false)
     * @param {Boolean} options.cylinder.topRadius  -用于指定圆柱体顶部的半径 (默认 0)
     * @param {Boolean} options.cylinder.bottomRadius  - 用于指定圆柱体底部的半径。 (默认 200)           
     * @param {Boolean} options.cylinder.material  - 指定用于填充圆柱体的材料 (默认 Color.RED)
     * @param {Boolean} options.cylinder.heightReference  - 指定距实体位置的高度是相对于什么的高度。 (默认 HeightReference.CLAMP_TO_GROUND)
     * @param {Object} options.polyline.material  - 绘制折线颜色 (默认 Color.RED)
     * @param {Boolean} options.ifTileset  - 是否贴模型漫游 (默认 false)
    */
    public modelRoaming(options: RoamingOptions) {
        this.modelData = {};
        this.Lines = options.Lines;
        let model = {
            minimumPixelSize: 64,
        };
        let path = {
            show: false
        }
        let polyline = {
            show: false,
            material: Color.RED,
        }
        let cylinder = {
            show: false,
            topRadius: 0.0,
            bottomRadius: 100.0,
            material: Color.RED.withAlpha(0.3),
            heightReference: HeightReference.CLAMP_TO_GROUND
        }
        let label = {
            show: false
        }
        this.ifAffixedTo = options.ifAffixedTo ?? false;
        this.ifClockLoop = options.ifClockLoop ?? false;
        this.interpolation = options.interpolation ?? false;
        this.showLabel = options.showLabel ?? false;
        this.ifTileset = options.ifTileset ?? false;
        this.modelData.model = Object.assign(model, options.model);
        this.modelData.path = Object.assign(path, options.path);
        this.modelData.label = Object.assign(label, options.label);
        this.modelData.polyline = Object.assign(polyline, options.polyline);
        this.modelData.cylinder = Object.assign(cylinder, options.cylinder);
        this.modelData.polyline.positions = new CallbackProperty(() => { }, false);
        this.modelData.cylinder.length = new CallbackProperty(() => { }, false);
        let property = this.ComputeRoamingLineProperty(this.Lines, this.time);
        this.modelInitRoaming(property, this.start, this.stop);
    }

    /**
     * 模型漫游
    */
    private modelInitRoaming(
        position: SampledPositionProperty,
        start: JulianDate,
        stop: JulianDate,
        orientation?: SampledProperty,
        radarPostion?: SampledPositionProperty,
    ) {
        // 初始化模型数据
        if (!this.modelData) {
            this.modelData = {
                model: {
                    minimumPixelSize: 64,
                },
                path: {
                    show: false
                },
                polyline: {
                    show: false,
                    material: Color.RED,
                },
                cylinder: {
                    show: false,
                    topRadius: 0.0,
                    bottomRadius: 100.0,
                    material: Color.RED.withAlpha(0.3),
                    heightReference: HeightReference.CLAMP_TO_GROUND
                },
                label: {
                    show: false
                }
            };
        }

        // 配置时钟
        this.viewer.clock.startTime = start.clone();
        this.viewer.clock.stopTime = stop.clone();
        this.viewer.clock.currentTime = start.clone();

        if (this.ifClockLoop) {
            this.viewer.clock.clockRange = ClockRange.LOOP_STOP;
        } else {
            this.viewer.clock.clockRange = ClockRange.CLAMPED;
            this.viewer.clock.clockStep = ClockStep.SYSTEM_CLOCK;
        }

        this.viewer.clock.shouldAnimate = true;
        this.viewer.clock.multiplier = this.multiplier;

        // 创建实体
        this.entity = this.viewer.entities.add({
            availability: new TimeIntervalCollection([new TimeInterval({
                start: start,
                stop: stop
            })]),
            position: position,
            orientation: orientation || new VelocityOrientationProperty(position),
            model: this.modelData.model,
            label: this.modelData.label,
            path: this.modelData.path,
        });

        // 应用插值设置
        if (!this.ifAffixedTo && this.interpolation && this.entity.position instanceof SampledPositionProperty) {
            (this.entity.position as SampledPositionProperty).setInterpolationOptions({
                interpolationDegree: 5,
                interpolationAlgorithm: LagrangePolynomialApproximation
            });
        }

        // 添加线条实体
        this.polyline = this.viewer.entities.add({
            polyline: this.modelData.polyline,
        });

        // 添加圆柱体实体
        this.cylinder = this.viewer.entities.add({
            position: position,
            orientation: new VelocityOrientationProperty(position),
            cylinder: this.modelData.cylinder
        });


        // 创建雷达特效
        if (radarPostion) {
            const cylinder = new CylinderBeam(this.viewer, null)
            this.radar = cylinder.createCylinderEntity(radarPostion);
        }

        // 处理动画
        this.setupAnimation();
        this.options.changeView && this.changingView(2);
    }

    // 单独创建动画设置函数
    private setupAnimation() {
        let positions: Cartesian3[] = [];
        // 动画回调
        let Exection = async () => {
            if (this.entity) {
                if (this.viewer.clock.shouldAnimate) {
                    //实时坐标
                    this.currentPosition = this.entity.position.getValue(this.viewer.clock.currentTime);

                    if (this.modelData.polyline.show && this.currentPosition) {
                        positions.push(this.currentPosition);
                        this.modelData.polyline.positions._callback = () => positions;
                    }
                    if (this.ifAffixedTo && this.currentPosition) {
                        let geoPt1 = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(this.currentPosition);
                        const terrainProvider = !this.viewer.terrainProvider.availability ?
                            await createWorldTerrainAsync() :
                            this.viewer.terrainProvider;

                        if (this.entity.position instanceof SampledPositionProperty) {
                            const updatedPositions = await sampleTerrainMostDetailed(terrainProvider, [
                                Cartographic.fromDegrees(
                                    geoPt1.longitude / Math.PI * 180,
                                    geoPt1.latitude / Math.PI * 180
                                )
                            ]);
                            (this.entity.position as SampledPositionProperty).addSample(
                                this.viewer.clock.currentTime,
                                Cartesian3.fromRadians(
                                    updatedPositions[0].longitude,
                                    updatedPositions[0].latitude,
                                    updatedPositions[0].height
                                )
                            );
                        }
                    }
                    if (this.ifTileset && this.currentPosition) {
                        const clampedPosition = this.viewer.scene.clampToHeight(this.currentPosition, [this.entity]);
                        if (clampedPosition && this.entity.position instanceof SampledPositionProperty) {
                            (this.entity.position as SampledPositionProperty).addSample(
                                this.viewer.clock.currentTime,
                                clampedPosition
                            );
                        }
                    }
                    if (this.modelData.cylinder.show && this.currentPosition) {
                        this.modelData.cylinder.length._callback = () => {
                            let length = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(this.currentPosition);
                            return length.height;
                        };
                    }
                    if (this.currentPosition) {
                        this.realTimeData(this.currentPosition);
                    }
                }
            } else {
                this.viewer.scene.preUpdate.removeEventListener(Exection);
            }
        };
        this.viewer.scene.preUpdate.addEventListener(Exection);
    }

    /**
     *漫游的暂停和继续
    *
    * @param {*} state bool类型 false为暂停，ture为继续
    * @memberof Roaming
    */
    private pauseOrContinue(state: boolean) {
        this.viewer.clock.shouldAnimate = state;
    }

    /**
     *改变飞行的速度
    *
    * @param {} value  整数类型
    * @memberof Roaming
    */private changeRoamingSpeed(value: number) {
        this.viewer.clock.multiplier = value;
    }
    /**
     *
     *取消漫游
    * @memberof Roaming
    */
    private endRoaming() {
        if (this.entity !== undefined) {
            this.viewer.entities.remove(this.entity);
            this.viewer.entities.remove(this.polyline);
            this.viewer.entities.remove(this.cylinder);
            this.entity = undefined;
            this.polyline = undefined;
            this.cylinder = undefined;
            this.pauseOrContinue(false);
        }
    }
    /**
     *
     *获取飞行数据
    * @memberof Roaming
    * @param {RequestCallback} callback - 回调函数 (单位米)。
    */
    private getData(callback: Function) {
        Object.defineProperty(this.data, 'shouldAnimate', {
            set: function (value) {
                return callback(this.data)
            }
        })
    }
    /**
     *切换视角
    * @memberof Roaming、
    * @param {Boolean} value   1视角跟踪 2上方视角 3侧方视角 4自定义视角
    * @param {Object} options 参数 自定义视角 模式时才有效
    * @param {Object} options.heading 可选 航向角（弧度）默认 0
    * @param {Object} options.pitch 可选俯仰角（弧度） 默认 0。
    * @param {Object} options.range 可选距中心的距离，以米为单位 默认 0。
    */
    private changingView(value: number, options?: { heading?: number; pitch?: number; range?: number }) {
        const opts = options || {};
        this.viewer.trackedEntity = undefined;
        if (value === 1) {
            this.viewer.trackedEntity = this.entity;
        } else if (value === 2) {
            this.viewer.zoomTo(this.entity,
                new HeadingPitchRange(0, CesiumMath.toRadians(-90), 100000)
            );
        } else if (value === 3) {
            this.viewer.zoomTo(this.entity,
                new HeadingPitchRange(
                    CesiumMath.toRadians(-90),
                    CesiumMath.toRadians(-15),
                    8000
                )
            );
        } else if (value === 4) {
            this.viewer.zoomTo(this.entity,
                new HeadingPitchRange(
                    CesiumMath.toRadians(opts.heading || 0),
                    CesiumMath.toRadians(opts.pitch || 0),
                    opts.range || 0
                )
            );
        }
    }

    /**
     * 实时数据
     * @param center 
     */
    private async realTimeData(center: Cartesian3) {
        this.data.shouldAnimate = this.viewer.clock.shouldAnimate;
        this.data.totalLength = this.disTance(this.Lines);//总长度
        this.data.totalTime = this.formateSeconds(this.time); //总时长
        const delTime = JulianDate.secondsDifference(this.viewer.clock.currentTime, this.viewer.clock.startTime);//已经漫游的时间
        this.data.delTime = this.formateSeconds(delTime);
        this.data.roamingLength = (Number(this.data.totalLength) / this.time * delTime).toFixed(3);//已经漫游长度
        const geoPt1 = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(center);
        this.data.longitude = (geoPt1.longitude / Math.PI * 180).toFixed(6);//经度
        this.data.latitude = (geoPt1.latitude / Math.PI * 180).toFixed(6);//纬度
        const terrainProvider = !this.viewer.terrainProvider.availability ? await createWorldTerrainAsync() : this.viewer.terrainProvider;
        const updatedPositions = await sampleTerrainMostDetailed(terrainProvider, [Cartographic.fromDegrees(geoPt1.longitude / Math.PI * 180, geoPt1.latitude / Math.PI * 180)]);
        this.data.roamingElevation = (updatedPositions[0].height + geoPt1.height).toFixed(2);//漫游高程
        this.data.terrainHeight = (updatedPositions[0].height).toFixed(2);//地面高程
        this.data.liftoffHeight = (Number(this.data.roamingElevation) - Number(this.data.terrainHeight)).toFixed(2);//离地距离
        this.data.progress = (Number(this.data.roamingLength) / Number(this.data.totalLength) * 100).toFixed(0) + '%';//进度
    }

    /**
     * 基于时间的位置属性计算
     * @param timePositions 时间位置数据数组
     * @returns 
     */
    private computeTimeBasedPositionProperty(timePositions: TimePositionData[], adjHeight: number = 0): SampledPositionProperty {
        const property = new SampledPositionProperty();
        property.setInterpolationOptions({
            interpolationDegree: 2,
            interpolationAlgorithm: HermitePolynomialApproximation
        });

        // 确定开始和结束时间
        const startTime = JulianDate.now();
        this.start = startTime;

        // 找到数据中的最大时间作为总时长
        const maxTime = Math.max(...timePositions.map(p => p.time));
        const stopTime = JulianDate.addSeconds(startTime, maxTime, new JulianDate());
        this.stop = stopTime;

        // 设置时钟
        this.viewer.clock.startTime = startTime.clone();
        this.viewer.clock.stopTime = stopTime.clone();
        this.viewer.clock.currentTime = startTime.clone();

        if (this.ifClockLoop) {
            this.viewer.clock.clockRange = ClockRange.LOOP_STOP;
        } else {
            this.viewer.clock.clockRange = ClockRange.CLAMPED;
            this.viewer.clock.clockStep = ClockStep.SYSTEM_CLOCK;
        }

        this.viewer.clock.shouldAnimate = true;
        this.viewer.clock.multiplier = this.multiplier;

        // 为每个时间点添加位置样本
        for (const point of timePositions) {
            const time = JulianDate.addSeconds(startTime, point.time, new JulianDate());
            const position = Cartesian3.fromDegrees(point.longitude, point.latitude, point.altitude - adjHeight);
            if (this.ifTileset) {
                const clampedPosition = this.viewer.scene.clampToHeight(position) || position;
                property.addSample(time, clampedPosition);
            } else {
                property.addSample(time, position);
            }
        }

        return property;
    }

    /**
     * 计算基于时间的姿态属性
     * @param timePositions 时间位置数据数组（包含姿态角）
     * @returns 姿态属性
     */
    private computeOrientationProperty(timePositions: TimePositionData[]): SampledProperty | undefined {
        // 检查是否有姿态角数据
        if (!timePositions.some(tp => tp.heading !== undefined || tp.pitch !== undefined || tp.roll !== undefined)) {
            return undefined;
        }

        const property = new SampledProperty(Quaternion);
        property.setInterpolationOptions({
            interpolationDegree: 2,
            interpolationAlgorithm: HermitePolynomialApproximation
        });

        const startTime = this.start || JulianDate.now();

        for (const tp of timePositions) {
            // 度数转弧度
            const time = JulianDate.addSeconds(startTime, tp.time, new JulianDate());
            const heading = CesiumMath.toRadians(tp.heading) || 0;
            const pitch = CesiumMath.toRadians(tp.pitch) || 0;
            const roll = CesiumMath.toRadians(tp.roll) || 0;

            const cartesian = Cartesian3.fromDegrees(tp.longitude, tp.latitude, tp.altitude);
            const orientation = Transforms.headingPitchRollQuaternion(
                cartesian,
                new HeadingPitchRoll(heading, pitch, roll)
            );

            property.addSample(time, orientation);
        }

        return property;
    }

    /**
     * 基于时间的模型漫游
     * @param timePositions 时间位置数据数组
     * @param options 漫游选项
     */
    public timeBasedModelRoaming(timePositions: TimePositionData[], options: RoamingOptions = {}) {
        this.modelData = {};
        // 将数据点转换为Cartesian3数组，用于距离计算等
        this.Lines = timePositions.map(point => {
            return Cartesian3.fromDegrees(point.longitude, point.latitude, point.altitude);
        });

        // 设置模型和路径属性
        let model = {
            minimumPixelSize: 64,
        };
        let path = {
            show: false
        };
        let polyline = {
            show: false,
            material: Color.RED,
        };
        let cylinder = {
            show: false,
            topRadius: 0.0,
            bottomRadius: 100.0,
            material: Color.RED.withAlpha(0.3),
            heightReference: HeightReference.CLAMP_TO_GROUND
        };
        let label = {
            show: false
        };

        // 应用选项
        this.ifAffixedTo = options.ifAffixedTo ?? false;
        this.ifClockLoop = options.ifClockLoop ?? false;
        this.interpolation = options.interpolation ?? false;
        this.showLabel = options.showLabel ?? false;
        this.ifTileset = options.ifTileset ?? false;
        this.options = options;

        this.modelData.model = Object.assign(model, options.model);
        this.modelData.path = Object.assign(path, options.path);
        this.modelData.label = Object.assign(label, options.label);
        this.modelData.polyline = Object.assign(polyline, options.polyline);
        this.modelData.cylinder = Object.assign(cylinder, options.cylinder);
        this.modelData.polyline.positions = new CallbackProperty(() => { }, false);
        this.modelData.cylinder.length = new CallbackProperty(() => { }, false);

        // 计算基于时间的位置属性
        const position = this.computeTimeBasedPositionProperty(timePositions);

        // 计算基于时间的姿态属性（如果有姿态角数据）
        const orientation = this.computeOrientationProperty(timePositions);

        // 雷达特效坐标
        let radarPostion: SampledPositionProperty;
        if (this.options.radar) {
            radarPostion = this.computeTimeBasedPositionProperty(timePositions, 500);
        }

        // 初始化漫游
        this.modelInitRoaming(position, this.start!, this.stop!, orientation, radarPostion);
    }

    /**
     *计算距离
    */
    private disTance(positions: Cartesian3[]): string {
        let distance = 0;
        for (let i = 0; i < positions.length - 1; i++) {
            const point1cartographic = Cartographic.fromCartesian(positions[i]);
            const point2cartographic = Cartographic.fromCartesian(positions[i + 1]);
            const geodesic = new EllipsoidGeodesic();
            geodesic.setEndPoints(point1cartographic, point2cartographic);
            let s = geodesic.surfaceDistance;
            s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2));
            distance += s;
        }
        return distance.toFixed(3);
    }

    /**
     * 将秒转化为时分秒
     * @param endTime 
     * @returns 
     */
    private formateSeconds(endTime: number): string {
        const secondTime = Math.floor(endTime);
        let min = 0;
        let h = 0;

        if (secondTime >= 60) {
            min = Math.floor(secondTime / 60);
            const remainingSeconds = secondTime % 60;

            if (min >= 60) {
                h = Math.floor(min / 60);
                min = min % 60;
            }

            return this.formatTimeString(h, min, remainingSeconds);
        }

        return this.formatTimeString(0, 0, secondTime);
    }

    /**
     * 格式化时间字符串
     * @param hours 
     * @param minutes 
     * @param seconds 
     * @returns 
     */
    private formatTimeString(hours: number, minutes: number, seconds: number): string {
        const h = hours === 0 ? '' : `${hours}小时`;
        const m = minutes === 0 ? '' : `${minutes}分钟`;
        const s = seconds === 0 ? '' : `${seconds}秒`;
        const result = `${h}${m}${s}`;
        return result === '' ? '0秒' : result;
    }

    public destroy() {
        if (this.entity) {
            this.viewer.entities.remove(this.entity);
            this.entity = null
        }
        if (this.polyline) {
            this.viewer.entities.remove(this.polyline);
        }
        if (this.cylinder) {
            this.viewer.entities.remove(this.cylinder);
        }
    }
}